home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / ab20 / ab20_archive / utilities / emulators / unixlib.lzh / select.c < prev    next >
C/C++ Source or Header  |  1991-10-22  |  4KB  |  155 lines

  1. /* this file contains some functions for handling the heartbeat. */
  2.  
  3. #include <sys/types.h>
  4. #include <exec/types.h>
  5. #include <exec/memory.h>
  6. #include <exec/tasks.h>
  7. #include <exec/interrupts.h>
  8. #include <devices/timer.h>
  9. #include <errno.h>
  10. #include <stdio.h>
  11. #include <signal.h>
  12. #include <functions.h>
  13.  
  14. /* our functions */
  15. void setup_exception(void);
  16. int alarm(int);
  17. void cleanexit(char *, LONG);
  18. void cleanup_exception(void);
  19.  
  20. static struct timerequest    *treq = NULL;
  21. static struct MsgPort        *tport = NULL;
  22. static BOOL OpenedTimer = FALSE;
  23. static int setup = 0;
  24. int eintr_signal;
  25.  
  26. extern int comm_time_to_call_heartbeat;
  27. extern int errno;
  28.  
  29.  
  30. static void setup_exception()
  31. {
  32.     /* allocate a signal , used in select() */
  33.     if((eintr_signal = AllocSignal(-1)) == -1)
  34.     cleanexit("Could not allocate EINTR signal\n", RETURN_FAIL);
  35.  
  36.     /* allocate a messageport */
  37.     if(!(tport = CreatePort(0L, 0L)))
  38.     cleanexit("Could not allocate port\n", RETURN_FAIL);
  39.  
  40.     if(!(treq = (struct timerequest *)
  41.         CreateExtIO(tport, sizeof(struct timerequest))))
  42.     cleanexit("Could not allocate message\n",RETURN_FAIL);
  43.  
  44.     /* open the timer device */
  45.     if(OpenDevice("timer.device", UNIT_MICROHZ, (struct IORequest* )treq, 0L))
  46.     cleanexit("Can't open timer device\n", RETURN_FAIL);
  47.  
  48.     OpenedTimer = TRUE;
  49.  
  50.     setup = 1;
  51. }
  52.  
  53. /* signal installs a handler for a given signal. */
  54. void signal(int sig, void (* handler) () )
  55. {
  56.     register ULONG except_signal;
  57.     register struct Task *this_task;
  58.  
  59.     if(!setup)
  60.     setup_exception();
  61.  
  62.     except_signal = 1L << tport->mp_SigBit;
  63.     this_task = FindTask(NULL);
  64.  
  65.     if(handler == SIG_IGN)
  66.     {    /* remove handler */
  67.     except_signal = this_task->tc_SigExcept;
  68.     SetExcept(0L, except_signal);
  69.     cleanup_exception();
  70.     }
  71.     else if(sig == SIGALRM)
  72.     {    /* install handler */
  73.     this_task->tc_ExceptCode = (APTR) handler;
  74.     SetExcept(except_signal, except_signal);
  75.     }
  76.     /* else do nothing .. */
  77. }
  78.  
  79.  
  80. /* clean up the mess made by a previous alarm, and set a new alarm up */
  81. int alarm(int seconds)
  82. {
  83.     while(GetMsg(tport))
  84.     ;
  85.     if(seconds > 0) {
  86.     /* set up the new timer command */
  87.     treq->tr_node.io_Command = TR_ADDREQUEST;
  88.     treq->tr_time.tv_secs = seconds;
  89.     treq->tr_time.tv_micro = 0;
  90.     SendIO((struct IORequest *) treq);
  91.     }
  92.     else
  93.     {
  94.     /* delete out-standing request */
  95.     AbortIO((struct IORequest *) treq);
  96.     WaitIO((struct IORequest *) treq);
  97.     while(GetMsg(tport))
  98.         ;
  99.     }
  100.     return 0;
  101. }
  102.  
  103.  
  104. static void cleanexit(char *s, LONG n)
  105. {
  106.     if(*s)  printf(s);
  107.     cleanup_exception();
  108.     exit(n);
  109. }
  110.  
  111.  
  112. static void cleanup_exception()
  113. {
  114.     if(OpenedTimer)    CloseDevice((struct IORequest *) treq);
  115.     OpenedTimer = 0;
  116.     if(treq)        DeleteExtIO((struct IORequest *) treq);
  117.     treq = 0;
  118.     if(tport)        DeletePort(tport);
  119.     tport = 0;
  120.     setup = 0;
  121. }
  122.  
  123. /* check if any signals from the sets are available
  124.  * return -1 if failure,
  125.  *         0 if time-out
  126.  * number of ready descriptor otherwise
  127.  * I use the heartbeat as timeout, but according to the UNIX-manual, an
  128.  * interrupted select() returns the unchanged masks. But we already cleared
  129.  * the signals, so the messages would not be read next time. So just save
  130.  * the ready sockets, so we can read them next time.
  131.  */
  132. int select (width, readfds, writefds, exceptfds, timeout)
  133.     int width;
  134.     register fd_set *readfds, *writefds, *exceptfds;
  135.     struct timeval *timeout;
  136. {
  137.     static fd_set saved = 0L;
  138.  
  139.     /* find all ready descriptors */
  140.     if(saved) {
  141.     *readfds = saved;  /* these were ready the last time already */
  142.     saved = 0L;       /* not needed anymore */
  143.     }
  144.     else
  145.     *readfds = Wait(*readfds | eintr_signal);
  146.  
  147.     if(*readfds & eintr_signal) {
  148.     saved = *readfds &~eintr_signal;
  149.     errno = EINTR;
  150.     return -1; /* Failure */
  151.     }
  152.  
  153.     return 1;  /* Well, this should be the number of ready descriptors */
  154. }
  155.